package com.augurit.smartform.factory;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import javax.script.Bindings;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import javax.script.SimpleBindings;

import com.augurit.common.util.lang.StringUtils;
import com.augurit.smartform.constant.FreeMarkerConstant;

import sun.org.mozilla.javascript.internal.Context;
import sun.org.mozilla.javascript.internal.Function;
import sun.org.mozilla.javascript.internal.NativeFunction;
import sun.org.mozilla.javascript.internal.NativeObject;
import sun.org.mozilla.javascript.internal.ScriptableObject;

public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String a=new String("abc");
		String b="abc";
		System.out.println(a.intern()==b);
//		Map m1=new HashMap();
//		Map m2=new HashMap();
//		m1.put("123", new Integer(10));
//		m1.put(new String("abc"), new Long(99));
//		m2.put(new String("123"), new Integer(10));
//		m2.put("abc", new Long(99));
//		System.out.println("(l1==l2)="+(m1.toString()+","+m1.toString()));
//		System.out.println("(l1==l2)="+(Long.toHexString(m1.hashCode())+","+Long.toHexString(m1.hashCode())));
//		System.out.println("(l1==l2)="+(m1.equals(m2)));
//		String l1=new String("123");
//		String l2="123";
//		System.out.println("(l1==l2)="+(Long.toHexString(l1.hashCode())+","+Long.toHexString(l2.hashCode())));
//		System.out.println("(l1==l2)="+(l1.toString()+","+l2.toString()));
//		test1();
//		test2();
//		System.out.println("thread="+Thread.currentThread().getContextClassLoader().getResource("com/augurit"));
//		System.out.println("file="+new File("/").getAbsolutePath());
//		System.out.println("user.dir="+System.getProperty("user.dir"));
//		System.out.println(ClassLoader.getSystemResource("com/augurit/common/smartform/template").getPath());
	}

	private static void test1(){
		String script=""
			+"println(\"Start script\");"
			
			+"function printType(obj) {"
			+" 	  if (obj.getClass)"
			+"        println(\"    Java object: \" + obj.getClass().name);"
			+"    else"
			+"        println(\"    JS object: \" + obj.toSource());"
			+"    println(\"\");"
			+"}"
			
			+"println(\"[JS] demoVar: \" + demoVar);"
			+"printType(demoVar);"
			+"strBuf.append(\" used in DemoScript.js\");"
			+"println(\"[JS] strBuf: \" + strBuf);"
			+"printType(strBuf);"
			+"demoVar = \"value set in DemoScript.js\";"
			+"println(\"[JS] demoVar: \" + demoVar);"
			+"printType(demoVar);"
			+"var newVar = { x: 1, y: { u: 2, v: \"3\" } };"
			+"println(\"[JS] newVar: \" + newVar);"
			+"printType(newVar);"
			+"println(\"End script \");"
			+"";
			
			
			ScriptEngine engine=ScriptEngineFactory.getScriptEngine();
			Bindings vars = new SimpleBindings();
	        vars.put("demoVar", "value set in ScriptDemo.java");
	        vars.put("strBuf", new StringBuffer("string buffer"));
	        try {
	        	engine.eval(script,vars);
			} catch (ScriptException e) {
				e.printStackTrace();
			}
			
	        Object demoVar = vars.get("demoVar");
	        System.out.println("[Java] demoVar: " + demoVar);
	        System.out.println("    Java object: " + demoVar.getClass().getName());
	        System.out.println();
	        Object strBuf = vars.get("strBuf");
	        System.out.println("[Java] strBuf: " + strBuf);
	        System.out.println("    Java object: " + strBuf.getClass().getName());
	        System.out.println();
	        NativeObject newVar=(NativeObject)vars.get("newVar");
	        System.out.println("[Java] newVar: " + newVar);
	        System.out.println("    Java object: " + newVar.getClass().getName());
	        Double x=(Double)newVar.getProperty(newVar, "x");
	        System.out.println("    newVar.x: " + x);
	        NativeObject y=(NativeObject)newVar.getProperty(newVar, "y");
	        Double u=(Double)y.getProperty(y, "u");
	        System.out.println("	newVar.y.u: "+u);
	        String v=(String)y.getProperty(y, "v");
	        System.out.println("	newVar.y.v: " + v);
	}
	
	private static void test2(){
		/*String script=""
		+"println(\"Start script \");"
		
		+"function printType(obj) {"
		+" 	  if (obj.getClass)"
		+"        println(\"    Java object: \" + obj.getClass().name);"
		+"    else"
		+"        println(\"    JS object: \" + obj.toSource());"
		+"    println(\"\");"
		+"}"
		
		+"function demoFunction(a, b) {"
		+"    println(\"[JS] a: \" + a);"
		+"    printType(a);"
		+"    println(\"[JS] b: \" + b);"
		+"    printType(b);"
		+"    var c = a + b;"
		+"    println(\"[JS] c: \" + c);"
		+"    printType(c);"
		+"    return c;"
		+"}"
		
		+"println(demoVar); "
		+"println(\"End script \"); "
		+"";
		
		ScriptEngine engine=ScriptEngineFactory.getScriptEngine();
		Bindings vars = new SimpleBindings();
		vars.put("demoVar", "value set in ScriptDemo.java");
		engine.setBindings(vars, ScriptContext.ENGINE_SCOPE);
        try {
        	engine.eval(script);
		} catch (ScriptException e) {
			e.printStackTrace();
		}
		
		if (engine instanceof Invocable) {
            Invocable invEngine = (Invocable) engine;
            Object result=null;
			try {
//				result = invEngine.invokeFunction("demoFunction", 1, 2.3);
				result = invEngine.invokeFunction("demoFunction", new Object[]{1,2.3});
			} catch (ScriptException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			}
            System.out.println("[Java] result: " + result);
            System.out.println("    Java object: "
                    + result.getClass().getName());
            System.out.println();
        } else{
            System.out.println("NOT Invocable");
        }*/

		
		String script=""
			+"Packages.java.lang.System.out.println(\"Start script \");"
			
			+"function printType(obj) {"
			+" 	  if (obj.getClass)"
			+"        Packages.java.lang.System.out.println(\"    Java object: \" + obj.getClass().name);"
			+"    else"
			+"        Packages.java.lang.System.out.println(\"    JS object: \" + obj.toSource());"
			+"    Packages.java.lang.System.out.println(\"\");"
			+"}"
			
			+"function demoFunction(a, b) {"
			+"    Packages.java.lang.System.out.println(\"[JS] a: \" + a);"
			+"    printType(a);"
			+"    Packages.java.lang.System.out.println(\"[JS] b: \" + b);"
			+"    printType(b);"
			+"    var c = a + b;"
			+"    Packages.java.lang.System.out.println(\"[JS] c: \" + c);"
			+"    printType(c);"
			+"    return c;"
			+"}"
			
			+"Packages.java.lang.System.out.println(\"End script \"); "
			+"";
		Context context=Context.enter();
		ScriptableObject scope=context.initStandardObjects();
		context.evaluateString(scope, script, null, 1, null);
		NativeFunction demoFunction=(NativeFunction)scope.getProperty(scope, "demoFunction");
//		NativeDate demoFunction=(NativeDate)scope.getProperty(scope, "demoFunction");
		System.out.println("    Java object: " + demoFunction.getClass().getName());
		Double[] args=new Double[]{Double.valueOf("4"),Double.valueOf("9")};
		Object value=demoFunction.call(context, scope, demoFunction, args);
		System.out.println("    Java object: " + value);
	}
	
}
